package net.hserver.admin.system.hook;

import cn.hserver.core.interfaces.HookAdapter;
import cn.hserver.core.ioc.annotation.Hook;
import cn.hserver.core.queue.HServerQueue;
import cn.hserver.plugin.web.context.HServerContextHolder;
import cn.hserver.plugin.web.interfaces.HttpRequest;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import net.hserver.admin.system.bean.OperLogEvent;
import net.hserver.admin.system.common.MyConstants;
import net.hserver.admin.system.config.Log;
import net.hserver.admin.system.entity.User;
import net.hserver.admin.system.utils.AuthUtils;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Hook(Log.class)
public class LogHook implements HookAdapter {
    private ThreadLocal<Object[]> args = new ThreadLocal<>();
    @Override
    public void before(Class aClass, Method method, Object[] objects) throws Throwable {
        args.set(objects);
    }

    @Override
    public Object after(Class aClass, Method method, Object o) {
        try {
            handleOperateLog(aClass, method, o, null);
            return o;
        }finally {
            args.remove();
        }
    }

    @Override
    public void throwable(Class aClass, Method method, Throwable throwable) {
        try {
            handleOperateLog(aClass, method, null, throwable);
        }finally {
            args.remove();
        }
    }

    private void handleOperateLog(Class aClass, Method method, Object res, Throwable e) {
        HttpRequest request = HServerContextHolder.getWebKit().httpRequest;
        String url = request.getUri();
        String requestMethod = request.getRequestType().name();
        OperLogEvent logEvent = new OperLogEvent();
        logEvent.setRequestMethod(requestMethod);
        logEvent.setOperUrl(url);
        logEvent.setClassName(aClass.getName());
        logEvent.setMethod(method.getName());
        logEvent.setOperTime(LocalDateTime.now());
        logEvent.setStatus(Boolean.TRUE);
        User loginUser = (User) AuthUtils.getUser();
        if (loginUser != null) {
            logEvent.setOperName(loginUser.getUsername());
        }else {
            logEvent.setOperName("未登录用户");
        }
        logEvent.setIp(request.getIpAddress());
        logEvent.setOperParam(StrUtil.sub(getRequestParam(args.get()), 0, 2000));
        logEvent.setJsonResult(StrUtil.sub(JSONUtil.toJsonStr(res), 0, 2000));
        if (e != null) {
            logEvent.setStatus(Boolean.FALSE);
            logEvent.setErrorMsg(e.getMessage());
        }
        HServerQueue.sendQueue(MyConstants.LOG_EVENT,logEvent);
    }

    private String getRequestParam(Object[] args) {
        if (args.length == 0) return "";
        List<Object> params = Arrays.stream(args).filter(i ->
                {
                    if (Objects.isNull(i)) return true;
                    String className = i.getClass().getName();
                    return className.contains("horgee")
                            || className.contains("java.lang");
                }
        ).toList();
        return JSONUtil.toJsonStr(params);
    }

}
